-module(pclique).
-export([pcliques/3]).

pcliques(G, Threads, IO)->
	process_flag(trap_exit, true),
	N = graph:v(G),
    F = set:get_el(N),
	Other = set:cross(set:diff(N, [F]),
					  set:diff(N, graph:adj(F,G))),
	PVertex = set:add(F, Other),
	spread(PVertex, N, [], G, IO, Threads, 0).


spread([F | Tail], N, D, G, IO, MaxThreads, CurrentThread)when CurrentThread<MaxThreads ->
	NewN = set:diff(N, [F]),
	spawn_link(clique, cliques, [ set:cross(NewN, graph:adj(F, G)),
								 set:cross(D, 	 graph:adj(F, G)),
								 [F], G, IO]),
	spread(Tail, NewN, set:add(F, D), G, IO,MaxThreads, CurrentThread+1);

spread([],_,_,_,_,_,CurrentThread)->
	end_process(CurrentThread);

spread(Vertex, N, D, G, IO, MaxThreads,_)->
	balancing(Vertex, N, D, G, IO, MaxThreads).

balancing(Vertex, N, D, G, IO, Threads)when length(Vertex)>0->
	receive
		{'EXIT',_,_}->
			new_process(Vertex, N, D, G, IO, Threads)
	end;

balancing([], _, _, _, _, Threads)->
	end_process(Threads).

end_process(Threads) when Threads>0 ->
	receive
		{'EXIT',_,_}->
			end_process(Threads - 1)
	end;
end_process(0)->
	ok.

new_process([F | Tail], N, D, G, IO, Threads)->
	NewN = set:diff(N, [F]),
	spawn_link(clique, cliques, [set:cross(NewN, graph:adj(F, G)),
								  set:cross(D, graph:adj(F, G)), [F], G, IO]),
	balancing(Tail, NewN, set:add(F, D), G, IO, Threads).
